package com.clay.appointment.service.Impl;

import com.alibaba.fastjson.JSONObject;
import com.clay.appointment.common.page.PageInfo;
import com.clay.appointment.entity.hospital.Schedule;
import com.clay.appointment.repository.ScheduleRepository;
import com.clay.appointment.service.DepartmentService;
import com.clay.appointment.service.HospitalService;
import com.clay.appointment.service.ScheduleService;
import com.clay.appointment.utils.BeanUtils;
import com.clay.appointment.vo.hospital.BookingScheduleRuleVo;
import com.clay.appointment.vo.hospital.ScheduleQueryVo;
import org.joda.time.DateTime;
import org.joda.time.DateTimeConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author : clay
 * @Description:
 * @Date: Create in 16:17 2021/8/8
 * @Modified By:
 */
@Service
public class ScheduleServiceImpl implements ScheduleService {
    @Autowired
    private ScheduleRepository scheduleRepository;

    @Autowired
    private MongoTemplate mongoTemplate;


    @Autowired
    private HospitalService hospitalService;

    @Autowired
    private DepartmentService departmentService;

    private Map<Integer, String> daysMap = new HashMap<>(16);

    {
        daysMap.put(DateTimeConstants.SUNDAY, "周日");
        daysMap.put(DateTimeConstants.MONDAY, "周一");
        daysMap.put(DateTimeConstants.TUESDAY, "周二");
        daysMap.put(DateTimeConstants.WEDNESDAY, "周三");
        daysMap.put(DateTimeConstants.THURSDAY, "周四");
        daysMap.put(DateTimeConstants.FRIDAY, "周五");
        daysMap.put(DateTimeConstants.SATURDAY, "周六");
    }

    @Override
    public void save(Map<String, Object> paramMap) {
        Schedule schedule1 = JSONObject.parseObject(JSONObject.toJSONString(paramMap), Schedule.class);
        Schedule schedule = scheduleRepository.getScheduleByHospitalCodeAndHospitalScheduleId(schedule1.getHospitalCode(), schedule1.getHospitalScheduleId());
        if (schedule != null) {
            BeanUtils.copyProperties(schedule1, schedule);
            scheduleRepository.save(schedule);
        } else {
            schedule1.setCreateTime(new Date());
            schedule1.setUpdateTime(new Date());
            schedule1.setDeleted(false);
            schedule1.setStatus(1);
            scheduleRepository.save(schedule1);
        }

    }

    @Override
    public PageInfo<Schedule> selectPage(int page, int limit, ScheduleQueryVo scheduleQueryVo) {
        Pageable pageable = PageRequest.of(page - 1, limit);
        Schedule schedule = new Schedule();
        BeanUtils.copyProperties(scheduleQueryVo, schedule);
        //创建Example对象
        ExampleMatcher matcher = ExampleMatcher.matching()
                .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)
                .withIgnoreCase(true);
        Example<Schedule> example = Example.of(schedule, matcher);
        Page<Schedule> all = scheduleRepository.findAll(example, pageable);
        return PageInfo.buildPage(all, Schedule.class);
    }

    @Override
    public void removeSchedule(String hospitalCode, String hospitalScheduleId) {
        //根据医院编号和科室编号查询信息
        Schedule schedule = scheduleRepository.getScheduleByHospitalCodeAndHospitalScheduleId(hospitalCode, hospitalScheduleId);
        if (schedule != null) {
            //调用方法删除
            scheduleRepository.deleteById(schedule.getId());
        }
    }

    @Override
    public Map<String, Object> getScheduleRule(Integer page, Integer limit, String hospitalCode, String departmentCode) {
        //根据医院编号和科室编号查询
        Criteria criteria = Criteria.where("hospitalCode")
                .is(hospitalCode)
                .and("departmentCode")
                .is(departmentCode);
        //根据工作日期workDate进行分组
        Aggregation agg = Aggregation.newAggregation(
                //匹配条件
                Aggregation.match(criteria),
                //分组字段
                Aggregation.group("workDate")
                        .first("workDate").as("workDate")
                        //统计号源数量
                        .count().as("doctorCount")
                        .sum("reservedNumber").as("reservedNumber")
                        .sum("availableNumber").as("availableNumber"),
                Aggregation.sort(Sort.Direction.DESC, "workDate"),
                //实现分页
                Aggregation.skip((long) ((page - 1) * limit)),
                Aggregation.limit(limit)
        );
        //调用方法，最终执行
        AggregationResults<BookingScheduleRuleVo> aggResults = mongoTemplate.aggregate(agg, Schedule.class, BookingScheduleRuleVo.class);
        List<BookingScheduleRuleVo> BookingScheduleRuleVoList = aggResults.getMappedResults();

        //分组查询的总记录数
        Aggregation totalAgg = Aggregation.newAggregation(
                Aggregation.match(criteria),
                Aggregation.group("workDate")
        );

        AggregationResults<BookingScheduleRuleVo> totalResults = mongoTemplate.aggregate(totalAgg, Schedule.class, BookingScheduleRuleVo.class);
        int total = totalResults.getMappedResults().size();
        //把日期对应星期获取
        for (BookingScheduleRuleVo bookingScheduleRuleVo : BookingScheduleRuleVoList) {
            Date workDate = bookingScheduleRuleVo.getWorkDate();
            String dayOfWeek = daysMap.get(new DateTime(workDate).getDayOfWeek());
            bookingScheduleRuleVo.setDayOfWeek(dayOfWeek);
        }


        //设置最终数据，进行返回
        Map<String, Object> result = new HashMap<>(16);
        result.put("BookingScheduleRuleList", BookingScheduleRuleVoList);
        result.put("total", total);

        //获取医院名称
        String hospitalName = hospitalService.getHospitalNameByHospitalCode(hospitalCode);
        //其他基础数据
        Map<String, String> baseMap = new HashMap<>(16);
        baseMap.put("hospitalName", hospitalName);
        result.put("baseMap", baseMap);
        return result;
    }

    @Override
    public List<Schedule> getDetailSchedule(String hospitalCode, String departmentCode, String workDate) {

        Date date = new DateTime(workDate).toDate();
        List<Schedule> scheduleList;
        //根据参数查询mongodb
        scheduleList = scheduleRepository
                .getScheduleByHospitalCodeAndDepartmentCodeAndWorkDate(hospitalCode, departmentCode, date);
        scheduleList.forEach(this::packageSchedule);
        return scheduleList;
    }

    /**
     * 封装排班详情其他值 医院名称、科室名称、日期对应星期
     *
     * @param schedule 时间表
     */
    private void packageSchedule(Schedule schedule) {
        Map<String, Object> param = schedule.getParam();
        String hospitalCode = schedule.getHospitalCode();
        String departmentCode = schedule.getDepartmentCode();
        //设置医院名称
        param.put("hospitalName", hospitalService.getHospitalNameByHospitalCode(hospitalCode));
        //设置科室编号
        String departmentName = departmentService
                .getDepartmentNameByDepartmentCodeAndHospitalCode(departmentCode, hospitalCode);
        param.put("departmentName", departmentName);
        //设置日期对应星期
        param.put("dayOfWeek", daysMap.get((new DateTime(schedule.getWorkDate())).getDayOfWeek()));
    }


}
